package com.jz.netthings.bloodsources.task;

import com.jz.netthings.bloodsources.bean.XyLink;
import com.jz.netthings.bloodsources.bean.XyNoPulping;
import com.jz.netthings.bloodsources.bean.XyRemind;
import com.jz.netthings.bloodsources.cache.BlodSourcesCache;
import com.jz.netthings.bloodsources.service.XyLinkService;
import com.jz.netthings.bloodsources.service.XyNoPulpingService;
import com.jz.netthings.bloodsources.service.XyRemindService;
import com.jz.netthings.exception.AdscmSystemException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 定时程序
 */
@Component
public class BloodSourcesTaskJob {

    Logger logger = LoggerFactory.getLogger(getClass());
    @Autowired
    XyLinkService xyLinkService;
    @Autowired
    XyRemindService xyRemindService;
    @Autowired
    XyNoPulpingService xyNoPulpingService;

    /**
     * 每天凌晨1点执行一次，执行定时程序
     */
    @Scheduled(cron = "0 1 0 * * ?")
    public void loadNewProviderDetails() throws AdscmSystemException {
        // 查询相关的血源数据进行缓存（JVM缓存)，如果数据量过大，请采用readis 或者mecached  等其它外部缓存技术，同时JVM缓存对服务器内存条大小有要求，建议16G内存
        // 经初步计算：1条血源链接记录约 16KB 字节大小，1W条数据约占用 156MB 内存大小 根据目前市场普遍硬件水平，项目服务器内存条大小 3G 即可满足 10W 条血源链接缓存的数据）
        // 物理服务器内存：8G-16G 目前业务主要为流线业务，该缓存目前未做查询使用，但是先做缓存功能
        // 查询需要处理的提醒记录信息
        new Thread(new CreateNoPulpingThread()).start();
        //查询需要处理的血源链接数据
        BlodSourcesCache.listDataForRemindFromXyLink =  xyLinkService.loadXyLinkToCache("");
        if(BlodSourcesCache.listDataForRemindFromXyLink !=null&&BlodSourcesCache.listDataForRemindFromXyLink.size()>=1){
            //证明有数据，则进行相关的数据数据存储
            try {
                insertRemindInfoFromXyLinkList(BlodSourcesCache.listDataForRemindFromXyLink);
                logger.info("每天凌晨1点执行一次，执行定时程序，查找新增浆员，查找血源链接数据是否需要生成提醒信息 【成功】 。。。。。。");
            } catch (Exception e) {
                logger.info("每天凌晨1点执行一次，执行定时程序，查找血源链接数据是否需要生成提醒信息 【错误】。。。。。。"+ e.getMessage());
            }
        }else {
            logger.info("每天凌晨1点执行一次，执行定时程序，查找血源链接数据是否需要生成提醒信息 【暂无数据】。。。。。。");
        }
    }

    /**
     * 血源链接数据处理方法
     * @param xyLinkData    血源链接数据集合
     * @return isSuccess    全部成功返回true,反之false
     * @throws Exception
     */
    public Boolean insertRemindInfoFromXyLinkList(List<XyLink> xyLinkData) throws Exception {
        Boolean isSuccess = false;
        BlodSourcesCache.listDataForRemind.clear();
        for (XyLink xyLink: xyLinkData) {
               //判定这批数据每条数据是否需要生成提醒信息
                if(xyLink.isRemind()){
                    XyRemind xyRemind =  new XyRemind();
                    xyRemind.setRemindNurseId(xyLink.getUseNurseId());        //护士ID
                    xyRemind.setRemindNurseName(xyLink.getUseNurseName());    //护士名称
                    xyRemind.setRemindNurseDeptId(xyLink.getUseNurseDeptId());//护士部门
                    xyRemind.setCardId(xyLink.getCardId());                   //浆员卡号
                    xyRemind.setRemindProviderId(xyLink.getLinkProviderId()); //浆员ID
                    xyRemind.setRemindProviderName(xyLink.getLinkProviderName()); //浆员名称
                    xyRemind.setRemindDate(new Date());                       //提醒时间
                    xyRemind.setNextCollDate(xyLink.getNextCollDate());       //下次献浆时间
                    xyRemind.setEstimateCollDate(xyLink.getNextCollDate());   //预计献浆时间 ≈下次献浆时间（如果前端用户不自定义更改的话）
                    BlodSourcesCache.listDataForRemind.add(xyRemind);
                }
        }
        if(BlodSourcesCache.listDataForRemind.size()>=1){
            isSuccess =  xyRemindService.insertXyRemindInfo(BlodSourcesCache.listDataForRemind,null);
        }else{
            logger.info("每天凌晨1点执行一次，执行定时程序，查找血源链接数据是否需要生成提醒信息 【暂无数据】。。。【"+BlodSourcesCache.listDataForRemind.size()+"】条。。。");
        }
        return isSuccess;
    };

    /**
     * 定义根据提醒记录已完成的数据进行浆员提醒预计献浆时间到底去献浆没有的结果判定集数据生成线程
     */
    class  CreateNoPulpingThread implements  Runnable{

        @Override
        public void run() {
            //软加载提醒的数据 从表【xy_remind】
            logger.info("每天凌晨1点执行一次，执行定时程序，查找【提醒记录数据】数据是否需要生成提醒信息 。。。。。。");
            try{
                loadXyRemindToCache();
            }catch (Exception e){
                logger.info("每天凌晨1点执行一次，执行定时程序，查找【提醒记录数据】数据是否需要生成提醒信息 【错误】。。。。。"+e.getMessage());
            }
        }
    }

    /**
     * 加载提醒数据方法
     */
    private void loadXyRemindToCache() throws AdscmSystemException{
        Boolean isSuccess = false;
        List<XyRemind> xyReminds =  xyRemindService.loadXyRemindToCache();
        if(xyReminds!=null && xyReminds.size()>=1){
            //证明有数据
                //遍历该数据
            BlodSourcesCache.listDataForNoPulping.clear();
            for (XyRemind xyRemind: xyReminds) {
                 //判断是否生成未献浆记录
                try {
                    //进行未献浆记录加工
                    if(xyRemind.isNoPulping()){
                        //查询该浆员对应Id的记录是否已存在未献浆记录里面了
                        List<XyNoPulping> xyNoPulpingList =  xyNoPulpingService.queryXyNoPulpingByProviderId(Integer.parseInt(xyRemind.getRemindProviderId()+""),1);
                        if(xyNoPulpingList!= null && xyNoPulpingList.size()>= 1){
                            //如果已经存在当前浆员的已再次献浆的记录，则重新生成一条当前浆员的未献浆记录，存到jvm待入库集合中
                                 BlodSourcesCache.listDataForNoPulping.add(covertNoPulpingFromRemind(xyRemind));
                        }else{
                            //如果不存在当前浆员已重新献浆的时间记录，则进行该浆员未重新献浆的数据状态
                            List<XyNoPulping> xyNoPulpingNoAiginList =  xyNoPulpingService.queryXyNoPulpingByProviderId(Integer.parseInt(xyRemind.getRemindProviderId()+""),2);
                            if(xyNoPulpingNoAiginList!=null && xyNoPulpingNoAiginList.size()>=1){
                                //↑ 说明该浆员已经有数据了，则进行其最新一条数据的状态更新
                                XyNoPulping xyNoPulping  = xyNoPulpingNoAiginList.get(0);
                                xyNoPulping =  covertUpdateDataForXyNoPulping(xyRemind,xyNoPulping);
                                xyNoPulpingService.updateByNoPulpingInfo(xyNoPulping);//此处为所有浆员的记录都更新信息
                            }else{
                                //↑ 证明该浆员没有未献浆的记录，则进行一条新记录的生成
                                BlodSourcesCache.listDataForNoPulping.add(covertNoPulpingFromRemind(xyRemind));
                            }

                        }
                    }else
                    //进行是否已再次献浆记录修改
                    if(xyRemind.getIsAgingPulping()){
                        //通过provederId更新相关的数据
                        XyNoPulping xyNoPulping = new XyNoPulping();
                        xyNoPulping.setProviderId(Integer.parseInt(xyRemind.getRemindProviderId()+""));
                        xyNoPulping.setAgingCollDate(xyRemind.getCollectionDate());
                        xyNoPulping.setIsAgingPulping(1);
                        xyNoPulpingService.updateByProviderId(xyNoPulping);         //此处为只更新最近的1条数据
                    }
                } catch (Exception e) {
                    logger.info("每天凌晨1点执行一次，执行定时程序，查找【提醒记录数据】数据是否需要生成提醒信息  【错误】。。。。。。"+e.getMessage());

                }
            }
            //进行未献浆记录数据入库生成
            if(BlodSourcesCache.listDataForNoPulping.size()>=1){
                xyNoPulpingService.insertXyNoPulpingInfo(BlodSourcesCache.listDataForNoPulping,null);
            }
        }
    }

    /**
     * 进行remind转换
     * @param xyRemind
     * @return
     */
    public XyNoPulping covertNoPulpingFromRemind(XyRemind xyRemind){
        XyNoPulping xyNoPulping =  new XyNoPulping();
        xyNoPulping.setCardId(xyRemind.getCardId());
        xyNoPulping.setProviderId(Integer.parseInt(xyRemind.getRemindProviderId()+""));
        xyNoPulping.setProviderName(xyRemind.getRemindProviderName());
        xyNoPulping.setLastCollDate(xyRemind.getCollectionDate());
        xyNoPulping.setCreateTime(new Date());
        xyNoPulping.setNurseId(Integer.parseInt(xyRemind.getRemindNurseId()+""));
        xyNoPulping.setNurseName(xyRemind.getRemindNurseName());
        xyNoPulping.setNurseDeptId(xyRemind.getRemindNurseDeptId());
        xyNoPulping.setCollectionDate(xyRemind.getCollectionDate());
        xyNoPulping.setNextCollDate(xyRemind.getNextCollDate());
        xyNoPulping.setEstimateNextCollDate(xyRemind.getEstimateCollDate());
        xyNoPulping.setDealUseTime(xyRemind.getOverConsumTime());
        xyNoPulping.setConStatus(2);
        xyNoPulping.setIsAgingPulping(2);
        xyNoPulping.setIsOutTask(2);
        return xyNoPulping;
    }

    /**
     * 进行内容更新赋值
     * @param xyRemind
     * @param xyNoPulping
     * @return
     */
    public XyNoPulping covertUpdateDataForXyNoPulping(XyRemind xyRemind,XyNoPulping xyNoPulping){
        if(xyRemind!=null&&xyNoPulping!=null){
            xyNoPulping.setLastCollDate(xyRemind.getCollectionDate());
            xyNoPulping.setCreateTime(new Date());
            xyNoPulping.setNurseId(Integer.parseInt(xyRemind.getRemindNurseId()+""));
            xyNoPulping.setNurseName(xyRemind.getRemindNurseName());
            xyNoPulping.setNurseDeptId(xyRemind.getRemindNurseDeptId());
            xyNoPulping.setCollectionDate(xyRemind.getCollectionDate());
            xyNoPulping.setNextCollDate(xyRemind.getNextCollDate());
            xyNoPulping.setEstimateNextCollDate(xyRemind.getEstimateCollDate());
        }
        return xyNoPulping;
    }
}
